#include "Vector.h"

/// Operações do vetor ///
TIPO_ELEMENTO Vector::norma() const
{
    TIPO_ELEMENTO resultado = 0;
    for(size_t i=0 ; i<(this->get_dimensao()) ; i++)
        resultado += pow((*this)(i),2);
    return(sqrt(resultado));
}

Vector Vector::operator+(const Vector& v) const
{
    // Checar se as dimensões dos vetores são iguais:
    if(this->get_dimensao() == v.get_dimensao())
    {
        Vector aux(this->get_dimensao());
        for(size_t i=0 ; i<(this->get_dimensao()) ; i++)
            aux(i) = (*this)(i) + v(i);
        return(aux);
    }
    else
    {
        cout<<get_nome()<<"operator+: os vetores tem dimensoes diferentes ("<<this->get_dimensao()<<" e "<<v.get_dimensao()<<")."<<endl;
        return(Vector());
    }
}

Vector Vector::operator-(const Vector& v) const
{
    // Checar se as dimensões dos vetores são iguais:
    if(this->get_dimensao() == v.get_dimensao())
    {
        Vector aux(this->get_dimensao());
        for(size_t i=0 ; i<(this->get_dimensao()) ; i++)
            aux(i) = (*this)(i) - v(i);
        return(aux);
    }
    else
    {
        cout<<get_nome()<<"operator-: os vetores tem dimensoes diferentes ("<<this->get_dimensao()<<" e "<<v.get_dimensao()<<")."<<endl;
        return(Vector());
    }
}

/// Outras operações entre vetores ///
Vector operator*(TIPO_ELEMENTO x, const Vector& v)
{
    Vector aux(v.get_dimensao());
    for(size_t i=0 ; i<v.get_dimensao() ; i++)
        aux(i) = x * v(i);
    return(aux);
}

Vector operator*(const Vector& v, TIPO_ELEMENTO x)
{
    return(x*v);
}

TIPO_ELEMENTO dotProduct(const Vector& primeiro, const Vector& segundo)
{
    // Checar se as dimensões dos vetores são iguais:
    if(primeiro.get_dimensao() == segundo.get_dimensao())
    {
        TIPO_ELEMENTO resultado = 0;
        for(size_t i=0 ; i<primeiro.get_dimensao() ; i++)
            resultado += primeiro(i) * segundo(i);
        return(resultado);
    }
    else
    {
        //cout<<primeiro.get_nome()<<"dotProduct: os vetores tem dimensoes diferentes ("<<primeiro.get_dimensao()<<" e "<<segundo.get_dimensao()<<")."<<endl;
        cout<<Vector().get_nome()<<"dotProduct: os vetores tem dimensoes diferentes ("<<primeiro.get_dimensao()<<" e "<<segundo.get_dimensao()<<")."<<endl;
        return(0);
    }
}

TIPO_ELEMENTO operator^(const Vector& primeiro, const Vector& segundo)
{
    return(dotProduct(primeiro,segundo));
}

Vector crossProduct(const Vector& primeiro, const Vector& segundo)
{
    // Checar se as dimensões dos vetores são iguais:
    if(primeiro.get_dimensao() == segundo.get_dimensao())
    {
        if(primeiro.get_dimensao() == 3)
        {
            Vector aux(primeiro.get_dimensao());
            aux(0) = primeiro(1)*segundo(2) - primeiro(2)*segundo(1);
            aux(1) = primeiro(2)*segundo(0) - primeiro(0)*segundo(2);
            aux(2) = primeiro(0)*segundo(1) - primeiro(1)*segundo(0);
            return(aux);
        }
        else
        {
            cout<<Vector().get_nome()<<"crossProduct: os vetores devem ter dimensao \"3\"."<<endl;
            return(Vector());
        }
    }
    else
    {
        cout<<Vector().get_nome()<<"crossProduct: os vetores tem dimensoes diferentes ("<<primeiro.get_dimensao()<<" e "<<segundo.get_dimensao()<<")."<<endl;
        return(Vector());
    }
}

Vector operator*(const Vector& primeiro, const Vector& segundo)
{
    return(crossProduct(primeiro,segundo));
}

TIPO_ELEMENTO angulo(const Vector& primeiro, const Vector& segundo)
{
    return(acos((primeiro^segundo)/(primeiro.norma()*segundo.norma())));
}

TIPO_ELEMENTO anguloGrau(const Vector& primeiro, const Vector& segundo)
{
    return((angulo(primeiro,segundo)*180)/M_PI);
}
